Computer programs and software are ubiquitous and are used not just to direct the functionality of conventional computers but also to control and enhance the functionality of myriad modern products and appliances. For instance, televisions, household appliances, cellular phones, automobiles, medical devices, and so forth, may incorporate computer programs which direct and enhance their functionality.
Increasingly, computers and computer processors are no longer simple single processors executing software in an instruction-by-instruction sequential fashion. The availability of multi-core processors and multiple-processor computing systems is increasing and the demand for concurrent (or parallel) software to take advantage of multi-processor computers and processors is also increasing. Computers and processors are increasingly multiple processors which can concurrently, or in parallel, execute multiple instructions and procedure threads simultaneously. Such concurrent processing (also referred to as “parallelism”) can greatly increase both the speed and processing power of computer systems when correctly exploited.
This increasing availability of multi-core and parallel computer processors is rapidly increasing the availability of parallelism in computing hardware and is greatly increasing the demand on developers to develop and redesign software to exploit the available parallelism. The use of parallelism and concurrency in programming is becoming increasingly more useful, important, and ubiquitous. However, in order to fully exploit the available parallelism, concurrent programs are typically fashioned, implemented, and executed in a way that protects data that might be accessed or modified by multiple concurrent threads of a concurrent process. Synchronization between different threads that may execute simultaneously in a concurrent program is an important component of developing and deploying correct concurrent software.
Software developers have used explicit lock-based synchronization to protect shared data during concurrent processing. However, explicit lock-based synchronization, specified by the software developer, may not be modular, may be error prone, and may not be easily maintained, extended, or modified.
Another solution to the synchronization problem is transactional memory where concurrent threads execute optimistically, assuming a conflict will not occur. In transactional memory, when a conflict does occur, conflicts may be detected after the fact and execution is then rolled back and repeated to alleviate the conflict. In cases of high contention, those cases where multiple conflicting concurrent threads are highly likely to run simultaneously, transactional memory can be very inefficient. Additionally, implementation of transactional memory often requires special hardware support. Transactional memory has also been implemented using software (i.e., software transactional memory). However, software transactional memory has other limitations, too. It is not well suited when programs have externally visible effects (for example if the program shows a message on a screen or writes a file to a disk), these actions are hard to—and sometimes cannot be—rolled back.
Better and more easily written concurrent programs would help to enable the exploitation of multi-core processors and parallel computing systems. Either locks or transactional memory may be employed for protection of shared data which may possibly be utilized by multiple threads during execution of concurrent threads in a concurrent process. Transactional memory will continue to be problematic in systems having high contention. Manually determining and hand coding locks can be both very tedious and time consuming for a software developer and can be prone to error. Further, it may be difficult for a software developer to know or keep track of each piece of data that is shared by multiple threads in a concurrent program or may become shared during subsequent modification or enhancement of the software. Consequently, manually determined locks are not easily extensible when concurrent software is modified or updated and may continue to be a significant source of error.
Using locks that are inferred at execution time may also prove problematic. Locks that are inferred at execution time may cause deadlocks or other bad behavior. Using locks of fine granularity may reduce contention, allowing more exploitation of parallelism, but fine grained locks may also be more difficult to determine and more prone to deadlock. Coarser grained locks might be easier to determine and may be less prone to deadlock but may also be likely to lead to higher contention, causing less exploitation of parallelism and less efficient runtime behavior of concurrent systems.